/** \file
* WIN32-specific implementation of the Mutex class.
* This file is part of Chorus, available at
* http://code.google.com/p/chorus-twitter/ . This file and all associated files
* and derivative works are bound by the terms of the LGPL 3.0 license,
* available at http://www.gnu.org/licenses/lgpl-3.0-standalone.html .
* \par Subversion URL:
* \$URL: http://chorus-twitter.googlecode.com/svn/branches/cpp/src/system/win32/Mutex.cpp $
* \version \$Rev: 153 $
* \date    \$Date: 2010-04-06 07:43:42 +0000 (Tue, 06 Apr 2010) $
*/

#define NEEDS_WIN32
#include "config.h"

#include "system/DebugConsole.hpp"
#include "system/Mutex.hpp"

using namespace std;

Mutex::Mutex()
{
	// Create the win32 mutex. Mutex code has to use unguarded debug console
	// calls so that they in turn don't call mutex (in case mutexes are
	// screwed up).
	mutex = CreateMutex(0, FALSE, 0);
	if (!mutex)
	{
		UNGUARDED_PDEBUG_WIN32("CreateMutex failed");
		return;
	}
}

Mutex::~Mutex()
{
	// Destroy the win32 mutex.
	if (mutex)
	{
		if (!CloseHandle(mutex))
			UNGUARDED_PDEBUG_WIN32("CloseHandle failed");
		mutex = 0;
	}
}

bool Mutex::lock()
{
	// Lock the mutex for an infinite amount of time.
	return lock(INFINITE);
}

bool Mutex::lock(unsigned timeoutms)
{
	// Do a timed wait on the mutex.
	switch (WaitForSingleObject(mutex, timeoutms))
	{
	case WAIT_ABANDONED:
		UNGUARDED_PDEBUG2("Warning - stale mutex:", (void*)mutex);
	case WAIT_OBJECT_0:
		return true;

	case WAIT_TIMEOUT:
		UNGUARDED_PDEBUG2("Warning - mutex lock timeout:", (void*)mutex);
		return false;

	default:
		UNGUARDED_PDEBUG_WIN32("WaitForSingleObject failed");
		return false;
	}
}

bool Mutex::unlock()
{
	// Do a simple mutex unlock.
	if (!ReleaseMutex(mutex))
	{
		UNGUARDED_PDEBUG_WIN32("ReleaseMutex failed");
		return false;
	}
	return true;
}
